package com.tsd.system.service.impl;

import com.tsd.core.utils.HlpUtils;
import com.tsd.core.utils.ListUtil;
import com.tsd.core.vo.HlpException;
import com.tsd.core.vo.PageBean;
import com.tsd.service.BaseServiceImpl;
import com.tsd.system.SysConstants;
import com.tsd.system.dao.SysResourceMapper;
import com.tsd.system.dao.SysRoleMapper;
import com.tsd.system.dao.SysUserRoleMapper;
import com.tsd.system.entity.*;
import com.tsd.system.service.SysRoleDataAccessRuleService;
import com.tsd.system.service.SysRoleResourceService;
import com.tsd.system.service.SysRoleService;
import com.tsd.system.service.SysUserRoleService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 描述：SysRole 服务实现层
 *
 * @author Hillpool
 * @date 2019/03/12 12:20:51
 */
@Service
public class SysRoleServiceImpl extends BaseServiceImpl implements SysRoleService {

    @Resource
    private SysRoleMapper sysRoleMapper;
    @Resource
    private SysUserRoleMapper sysUserRoleMapper;
    @Resource
    private SysRoleResourceService sysRoleResourceService;
    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    private SysRoleDataAccessRuleService sysRoleDataAccessRuleService;
    @Resource
    SysResourceMapper sysResourceMapper;

    @Override
    public SysRole getSysRoleById(Long id) throws Exception {
        return sysRoleMapper.selectByPrimaryKey(id);
    }

    @Override
    public SysRoleExt queryBySid(String sid) throws Exception {
        return sysRoleMapper.selectBySid(sid);
    }

    @Override
    public void saveSysRole(SysRoleExt record, SysUser sysUser) throws Exception {
        super.checkEmpty(record.getName(), "缺少角色名称");
        super.checkEmpty(record.getCode(), "缺少角色编码");
        super.checkEmptyList(record.getResourceList(), "角色权限不能为空");
        this.selectDuplicatedRecord(record);
        if (HlpUtils.isEmpty(record.getId())) {
            super.autoInjectBaseData(record, sysUser, this.TYPE_CREATE);
            sysRoleMapper.insertSelective(record);
        } else {
            super.autoInjectBaseData(record, sysUser, this.TYPE_UPDATE);
            sysRoleMapper.updateByPrimaryKeySelective(record);
        }

        List<String> resourceIdList = ListUtil.map(record.getResourceList(), SysRoleResource::getResource_sid);
        sysRoleResourceService.saveSysResourceList2Role(sysUser, record.getSid(), resourceIdList, record.getResourceList());
    }

    private void selectDuplicatedRecord(SysRoleExt record) throws HlpException {
        SysRoleExt params = new SysRoleExt();
        if (!HlpUtils.isEmpty(record.getId())) {
            params.setId(record.getId());
        }
        params.setName(record.getName());
        SysRoleExt old = sysRoleMapper.selectDuplicatedRecord(params);
        if (old != null) {
            throw new HlpException("存在重复名称的角色，请重新录入");
        }
        params.setName(null);
        params.setCode(record.getCode());
        old = sysRoleMapper.selectDuplicatedRecord(params);
        if (old != null) {
            throw new HlpException("存在重复编码的角色，请重新录入");
        }
    }

    @Override
    public void deleteSysRole(Long id, SysUser sysUser) throws Exception {
        sysRoleMapper.deleteByPrimaryKey(id);
    }

    @Override
    public void batchDelSysRole(List<Long> ids, SysUser opUser) throws Exception {
        for (Long id : ids) {
            SysRole old = sysRoleMapper.selectByPrimaryKey(id);
            super.autoInjectBaseData(old, opUser, this.TYPE_DELETE);
            sysRoleMapper.updateByPrimaryKeySelective(old);
        }
    }

    @Override
    public List<SysRoleExt> findSysRoles(Map<String, Object> params, PageBean page) throws Exception {
        List<SysRoleExt> list = sysRoleMapper.selectByPage(params, page);
        if (!HlpUtils.isEmptyList(list)) {
            this.procWithRewsource(list, params);
            this.procWithAccessRule(list, params);
        }
        return list;
    }

    @Override
    public List<SysRoleExt> findSysRoles(Map<String, Object> params) throws Exception {
        List<SysRoleExt> list = sysRoleMapper.selectByParams(params);
        if (!HlpUtils.isEmptyList(list)) {
            this.procWithRewsource(list, params);
        }
        return list;
    }

    private void procWithRewsource(List<SysRoleExt> list, Map<String, Object> params) throws Exception {
        if (params.containsKey("with_resource")) {
            List<String> roleList = ListUtil.map(list, SysRoleExt::getSid);
            List<SysRoleResourceExt> roleResourceExtList = sysRoleResourceService.queryValidByRoleList(roleList);
            if (!HlpUtils.isEmptyList(roleResourceExtList)) {
                for (SysRoleExt roleExt : list) {
                    List<SysRoleResourceExt> filterList = ListUtil.filter(roleResourceExtList, t -> roleExt.getSid().equals(t.getRole_sid()));
                    List<String> resourceList = ListUtil.map(filterList, SysRoleResourceExt::getResource_sid);
                    roleExt.setResource_list(resourceList);
                }
            }
        }
    }

    private void procWithAccessRule(List<SysRoleExt> list, Map<String, Object> params) throws Exception {
        List<String> roleList = ListUtil.map(list, SysRoleExt::getSid);
        List<SysRoleDataAccessRule> roleAccessRuleExtList = sysRoleDataAccessRuleService.queryValidByRoleList(roleList);
        if (!HlpUtils.isEmptyList(roleAccessRuleExtList)) {
            for (SysRoleExt roleExt : list) {
                List<SysRoleDataAccessRule> filterList = ListUtil.filter(roleAccessRuleExtList, t -> roleExt.getSid().equals(t.getRole_sid()));
                List<String> accessRuleList = ListUtil.map(filterList, SysRoleDataAccessRule::getAccess_rule_sid);
                roleExt.setAccess_rule_list(accessRuleList);
            }
        }
    }

    @Override
    public List<SysRoleExt> findRoleByUnitType(String orgTypeSid) throws Exception {
        return sysRoleMapper.selectRoleByUnitType(orgTypeSid);
    }

    @Override
    public List<Map<String, Object>> findParamsMapByPage(Map<String, Object> params, PageBean page) throws Exception {
        return sysRoleMapper.selectParamsMapByPage(params, page);
    }

    @Override
    public void batchDeleteSysRole(List<Long> ids, SysUser opUser) throws Exception {
        for (Long id : ids) {
            deleteSysRole(id, opUser);
        }
    }

    @Override
    public List<SysRoleExt> findRoleListByUserId(Map<String, Object> params) throws Exception {
        List<SysUserRoleExt> sysUserRoleExts = sysUserRoleMapper.selectByUserSid(params);
        List<SysRoleExt> list = new ArrayList<>();
        if (!HlpUtils.isEmptyList(sysUserRoleExts)) {
            SysUserRoleExt sysUserRole = sysUserRoleExts.get(0);
            SysRoleExt sysRole = sysRoleMapper.selectBySid(sysUserRole.getRole_sid());
            list = extendParent(list, sysRole);
        }
        return list;
    }

    @Override
    public void saveSysUserRoleList(SysRoleExt record, SysUser sysUser, List<String> user_sid_list) throws Exception {
        List<SysUserRole> oldList = sysUserRoleMapper.selectByRoleSid(record.getSid());
        //不存在角色的编号进行删除
        List<Long> delIds = ListUtil.filterMap(oldList, t -> !user_sid_list.contains(t.getUser_sid()), SysUserRole::getId);
        if (!delIds.isEmpty()) {
            for (Long id : delIds) {
                sysUserRoleService.deleteLogicalUserRoleById(id, sysUser);
            }
        }
        List<String> oldUserList = ListUtil.map(oldList, SysUserRole::getUser_sid);
        List<String> addUserList = ListUtil.filter(user_sid_list, t -> !oldUserList.contains(t));
        if (!HlpUtils.isEmptyList(addUserList)) {
            List<SysUserRole> insertList = new ArrayList<>();
            for (String userSid : addUserList) {
                SysUserRole userRole = new SysUserRole();
                userRole.setUser_sid(userSid);
                userRole.setRole_sid(record.getSid());
                super.autoInjectBaseData(userRole, sysUser, this.TYPE_CREATE);
                insertList.add(userRole);
            }
            sysUserRoleMapper.insertList(insertList);
        }
    }

    @Override
    public List<SysRoleExt> query4ShiroAuthorizationInfo(SysUserExt userExt) throws Exception {
        String userSid = userExt.getSid();
        if (!HlpUtils.isEmpty(userExt.getLogin_id()) && SysConstants.LOGIN_ID4ADMIN.equals(userExt.getLogin_id())) {
            userSid = null;
        }
        return sysRoleMapper.select4ShiroByUserSid(userSid);
    }

    @Override
    public void initRoleAll(SysUserExt admin) throws Exception {
        Map<String, Object> params = new HashMap<>();
        params.put("dr", 0);
        List<SysResourceExt> resourceExts = sysResourceMapper.selectByParams(params);
        SysRoleExt all = new SysRoleExt();
        all.setCode("all");
        all.setName("所有功能");
        this.selectDuplicatedRecord(all);
        super.autoInjectBaseData(all, null, this.TYPE_CREATE);
        //创建角色
        sysRoleMapper.insertSelective(all);
        //设置角色拥有所有权限
        List<SysRoleResource> srrList = new ArrayList<>();
        for (SysResourceExt r : resourceExts) {
            SysRoleResource srr = new SysRoleResource();
            srr.setResource_sid(r.getSid());
            srr.setRole_sid(all.getSid());
            srr.setCheck_type(1);
            srrList.add(srr);
        }
        List<String> resourceIdList = ListUtil.map(resourceExts, SysResourceExt::getSid);
        sysRoleResourceService.saveSysResourceList2Role(null, all.getSid(), resourceIdList, srrList);
        List<String> user_sid_list = new ArrayList<>(1);
        user_sid_list.add(admin.getSid());
        //设置用户admin关联角色all
        this.saveSysUserRoleList(all, null, user_sid_list);
    }

    private List<SysRoleExt> extendParent(List<SysRoleExt> list, SysRoleExt sysRole) {
        SysRoleExt parent = sysRoleMapper.selectBySid(sysRole.getParent_sid());
        if (parent != null) {
            list.add(parent);
            return extendParent(list, parent);
        }
        return list;
    }


    @Override
    public List<SysRoleExt> listSysRole(Map<String, Object> params, PageBean page) throws Exception {
        return sysRoleMapper.listSysRole(params);
    }

    @Override
    public List<SysRoleExt> findSysRoleTree(String groupId) throws Exception {
        List<SysRoleExt> list = sysRoleMapper.selectByParentSid(groupId);
        for (SysRoleExt role : list) {
            expandRole(role);
        }
        return list;
    }

    /**
     * 展开到一个列表中
     *
     * @param role
     */
    private void expandRole(SysRoleExt role) {
        List<SysRoleExt> items = sysRoleMapper.selectByParentSid(role.getSid());
        role.setChildrens(items);
        for (SysRoleExt c : items) {
            expandRole(c);
        }
    }
}
